package com.litorg.demo.db.utils;

import com.litorg.demo.db.vo.Test1VO;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class SpelUtil {

    /**
     * 用于SpEL表达式解析.
     */
    private static final SpelExpressionParser parser = new SpelExpressionParser();

    /**
     * 用于获取方法参数定义名字.
     */
    private static final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();

    /**
     * 解析SpEL表达式
     *
     * @param spELStr
     * @param joinPoint
     * @return
     */
    public static String excute(String spELStr, JoinPoint joinPoint) {
        // 通过joinPoint获取被注解方法
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 使用Spring的DefaultParameterNameDiscoverer获取方法形参名数组
        String[] paramNames = nameDiscoverer.getParameterNames(method);
        // 解析过后的Spring表达式对象
        Expression expression = parser.parseExpression(spELStr);
        // Spring的表达式上下文对象
        EvaluationContext context = new StandardEvaluationContext();
        // 通过joinPoint获取被注解方法的形参
        Object[] args = joinPoint.getArgs();
        // 给上下文赋值
        for (int i = 0; i < args.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        // 表达式从上下文中计算出实际参数值
        /*如:
            @annotation(key="#user.name")
            method(User user)
             那么就可以解析出方法形参的某属性值，return “xiaoming”;
          */
        return expression.getValue(context).toString();
    }

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("a", "val1");
        map.put("b", "val2");
        map.put("c", "val3");
        List<Test1VO> ll = new ArrayList<>();
        Test1VO vo1 = new Test1VO();
        vo1.setEquipmentName("name1");
        Test1VO vo2 = new Test1VO();
        vo2.setEquipmentName("name2");
        Test1VO vo3 = new Test1VO();
        vo3.setEquipmentName("name3");
        ll.add(vo1);
        ll.add(vo2);
        ll.add(vo3);
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("map", map);
        context.setVariable("ll", ll);
        Expression expression = parser.parseExpression("#ll.?[#this.equipmentName == \"name1\"]");
        Object value = expression.getValue(context);
        System.out.println();
        // String s = expression.getValue(context, String.class);
        // System.out.println(s);
    }
}